Fix `--message-format JSON` when rustc emits non-JSON warnings
authorfmdkdd <fmdkdd@gmail.com>
Thu, 15 Dec 2016 23:05:58 +0000 (00:05 +0100)
committerfmdkdd <fmdkdd@gmail.com>
Thu, 15 Dec 2016 23:05:58 +0000 (00:05 +0100)
The `--message-format JSON` flag parses all the stderr output of rustc to JSON,
but rustc can emit non-JSON lines to stderr (e.g., for warning about the
unstable `-Z` flag on the stable channel), causing cargo to fail reporting
compilation errors when using `--message-format JSON`.

This commit adds a check to look for lines beginning with `{` to only parse
these lines as JSON.  Other lines from rustc are forwarded to the stderr of
cargo.

Fixes #3390.

src/cargo/ops/cargo_rustc/mod.rs

index 6c59910537cbc913a98b211bef53a41e655885e1..24f9deb0a80da27498fdd7bdcdc6b4acdbfa1b9b 100644 (file)
@@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fs;
+use std::io::{self, Write};
 use std::path::{self, PathBuf};
 use std::sync::Arc;
 
@@ -297,15 +298,22 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
                     Ok(())
                 },
                 &mut |line| {
-                    let compiler_message = json::Json::from_str(line).map_err(|_| {
-                        internal(&format!("compiler produced invalid json: `{}`", line))
-                    })?;
-
-                    machine_message::emit(machine_message::FromCompiler {
-                        package_id: &package_id,
-                        target: &target,
-                        message: compiler_message,
-                    });
+                    // stderr from rustc can have a mix of JSON and non-JSON output
+                    if line.starts_with("{") {
+                        // Handle JSON lines
+                        let compiler_message = json::Json::from_str(line).map_err(|_| {
+                            internal(&format!("compiler produced invalid json: `{}`", line))
+                        })?;
+
+                        machine_message::emit(machine_message::FromCompiler {
+                            package_id: &package_id,
+                            target: &target,
+                            message: compiler_message,
+                        });
+                    } else {
+                        // Forward non-JSON to stderr
+                        writeln!(io::stderr(), "{}", line)?;
+                    }
                     Ok(())
                 },
             ).map(|_| ())